package cn.hallele.bbts.core.common.utils;

import cn.hallele.bbts.core.common.constants.MsgCodeConst;
import cn.hallele.bbts.core.common.exceptions.CoreException;
import cn.hallele.bbts.core.component.io.BBTSPage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.io.*;
import java.util.List;

/**
 * BeanUtil
 *
 * @author anle5
 * @since 2023/11/30 星期四 23:47
 */
@Slf4j
public class BeanUtil {
    /**
     * bean转换,使用json序列化 反序列化的方式转换
     *
     * @param ori    原对象
     * @param tClass 目标class
     * @param <T>    目标值
     * @return 转换后的目标值
     */
    public static <T> T transferBean(Object ori, Class<T> tClass) {
        try {
            T t = tClass.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(ori, t);
            return t;
        } catch (Exception e) {
            log.error("Bean [{}] -> [{}] transfer failed.", ori.getClass(), tClass, e);
            throw new CoreException(MsgCodeConst.BEAN_COPY_FAILED, ori.getClass(), tClass);
        }
    }

    /**
     * bean转换,使用json序列化 反序列化的方式转换
     *
     * @param objects 原对象集合
     * @param tClass  目标class
     * @param <T>     目标值
     * @return 转换后的目标值
     */
    public static <T> List<T> transferBeanList(List<?> objects, Class<T> tClass) {
        return objects.stream().map(o -> transferBean(o, tClass)).toList();
    }

    /**
     * bean转换,使用json序列化 反序列化的方式转换
     *
     * @param ori    原对象分页集合
     * @param tClass 目标class
     * @param <T>    目标值
     * @return 转换后的目标值
     */
    public static <T> BBTSPage<List<T>> transferPage(BBTSPage<List<?>> ori, Class<T> tClass) {
        return BBTSPage.<List<T>>builder()
                .body(transferBeanList(ori.getBody(),tClass))
                .pageNo(ori.getPageNo())
                .pageSize(ori.getPageSize())
                .totalPages(ori.getTotalPages())
                .totalNum(ori.getTotalNum())
                .build();
    }

    /**
     * 对象序列化为byte数组
     *
     * @param ori obj
     * @return byte[]
     */
    public static byte[] bean2Byte(Object ori) {
        byte[] bb = null;
        try (ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
             ObjectOutputStream outputStream = new ObjectOutputStream(byteArray)) {
            outputStream.writeObject(ori);
            outputStream.flush();
            bb = byteArray.toByteArray();
        } catch (IOException e) {
            log.error("Bean2Byte [{}] -> [bytes] transfer failed.", ori.getClass(), e);
            throw new CoreException(MsgCodeConst.BEAN_COPY_FAILED, ori.getClass(), "bytes");
        }
        return bb;
    }

    /**
     * 字节数组转为Object对象
     *
     * @param bytes bytes
     * @return Object
     */
    public static Object byte2Obj(byte[] bytes) {
        Object readObject = new Object();
        try (ByteArrayInputStream in = new ByteArrayInputStream(bytes);
             ObjectInputStream inputStream = new ObjectInputStream(in)) {
            readObject = inputStream.readObject();
        } catch (Exception e) {
            log.error("Bean2Byte [bytes] -> [{}] transfer failed.", readObject.getClass(), e);
            throw new CoreException(MsgCodeConst.BEAN_COPY_FAILED, "byte", readObject.getClass());
        }
        return readObject;
    }
}
